<!doctype html>
<!--
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
  <title>core-resizable tests</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
  <script src="../../webcomponentsjs/webcomponents.js"></script>
  <script src="../../web-component-tester/browser.js"></script>
  <link rel="import" href="../core-resizable.html">
  <link rel="import" href="test-elements.html">
</head>
<body fit>

<!-- 

Notes on Polyfill compatibility in tests:
- Test elements loaded via imports, to ensure load order correctness
  w.r.t. Polymer.mixin being availbale
- Resize notifications and asserts are done asynchronously, since
  there are timing differences w.r.t. when detached callbacks occur

-->

<polymer-element name='test-element' noscript>
  <template>

    <!-- Normal CoreResizer parent with child CoreResizables -->
    <core-resizer-parent id="parent">
      <core-resizable id="child1a"></core-resizable>
      <div>
        <core-resizable id="child1b"></core-resizable>
      </div>
      <core-resizable-in-shadow id="shadow1c"></core-resizable-in-shadow>
      <div>
        <core-resizable-in-shadow id="shadow1d"></core-resizable-in-shadow>
      </div>
    </core-resizer-parent>

    <!-- CoreResizer parent using shouldNotify, with child CoreResizables -->
    <core-resizer-parent-filtered id="parentFiltered">
      <core-resizable id="child2a"></core-resizable>
      <div>
        <core-resizable id="child2b"></core-resizable>
      </div>
      <core-resizable-in-shadow id="shadow2c"></core-resizable-in-shadow>
      <div>
        <core-resizable-in-shadow id="shadow2d"></core-resizable-in-shadow>
      </div>
    </core-resizer-parent-filtered>

    <!-- CoreResizer using resizerIsPeer:true, with peer CoreResizables -->
    <div>
      <core-resizable id="child3a"></core-resizable>
      <div>
        <core-resizable id="child3b"></core-resizable>
      </div>
      <core-resizer-peer id="peer"></core-resizer-peer>
      <core-resizable-in-shadow id="shadow3c"></core-resizable-in-shadow>
      <div>
        <core-resizable-in-shadow id="shadow3d"></core-resizable-in-shadow>
      </div>
    </div>

    <!-- CoreResizer using resizerIsPeer:true and shouldNotify, with peer CoreResizables -->
    <div>
      <core-resizable id="child4a"></core-resizable>
      <div>
        <core-resizable id="child4b"></core-resizable>
      </div>
      <core-resizer-peer-filtered id="peerFiltered"></core-resizer-peer-filtered>
      <core-resizable-in-shadow id="shadow4c"></core-resizable-in-shadow>
      <div>
        <core-resizable-in-shadow id="shadow4d"></core-resizable-in-shadow>
      </div>
    </div>

    <!-- Nested CoreResizers -->
    <core-resizer-parent id="parentTop">
      <core-resizer-parent id="parentNested">
        <core-resizable id="child5a"></core-resizable>
        <core-resizer-peer id="peerNested"></core-resizer-peer>
        <div>
          <core-resizable-in-shadow id="shadow5b"></core-resizable-in-shadow>
        </div>
      </core-resizer-parent>
    </core-resizer-parent>

  </template>

</polymer-element>

<test-element></test-element>

<script>

  document.addEventListener('polymer-ready', function() {

    var testEl = document.querySelector('test-element');

    var registered = [];
    var notifyPending = [];
    var registerResizeHandler = function(el, expectNotification) {
      registered.push(el);
      if (expectNotification !== false) {
        notifyPending.push(el);
      }
      el.resizeHandler = function() {
        var idx = notifyPending.indexOf(this);
        if (idx < 0) {
          debugger;
        }
        assert(idx >= 0, 'resize notified to unexpected resizable ' + this.localName + '#' + this.id);
        notifyPending.splice(idx, 1);
      }.bind(el);
    };
    var unregisterResizeHandlers = function() {
      registered.forEach(function(r) {
        r.resizeHandler = null;
      });
      registered = [];
      notifyPending = [];
    };

    suite('core-resizer-parent', function() {

      test('notify resizables from window', function(done) {
        registerResizeHandler(testEl.$.parent);
        registerResizeHandler(testEl.$.child1a);
        registerResizeHandler(testEl.$.child1b);
        registerResizeHandler(testEl.$.shadow1c.$.resizable);
        registerResizeHandler(testEl.$.shadow1d.$.resizable);
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from parent', function(done) {
        registerResizeHandler(testEl.$.parent);
        registerResizeHandler(testEl.$.child1a);
        registerResizeHandler(testEl.$.child1b);
        registerResizeHandler(testEl.$.shadow1c.$.resizable);
        registerResizeHandler(testEl.$.shadow1d.$.resizable);
        setTimeout(function() {
          testEl.$.parent.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach resizables then notify parent', function(done) {
        registerResizeHandler(testEl.$.parent);
        registerResizeHandler(testEl.$.child1a, false);
        registerResizeHandler(testEl.$.child1b);
        registerResizeHandler(testEl.$.shadow1c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow1d.$.resizable);
        testEl.$.child1a.remove();
        testEl.$.shadow1c.remove();
        setTimeout(function() {
          testEl.$.parent.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach parent then notify window', function(done) {
        registerResizeHandler(testEl.$.parent, false);
        registerResizeHandler(testEl.$.child1a, false);
        registerResizeHandler(testEl.$.child1b, false);
        registerResizeHandler(testEl.$.shadow1c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow1d.$.resizable, false);
        testEl.$.parent.remove();
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

    });

    suite('core-resizer-parent-filtered', function() {

      test('notify resizables from window', function(done) {
        registerResizeHandler(testEl.$.parentFiltered);
        registerResizeHandler(testEl.$.child2a);
        registerResizeHandler(testEl.$.child2b, false);
        registerResizeHandler(testEl.$.shadow2c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow2d.$.resizable, false);
        testEl.$.parentFiltered.active = testEl.$.child2a;
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from parent', function(done) {
        registerResizeHandler(testEl.$.parentFiltered);
        registerResizeHandler(testEl.$.child2a);
        registerResizeHandler(testEl.$.child2b, false);
        registerResizeHandler(testEl.$.shadow2c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow2d.$.resizable, false);
        testEl.$.parentFiltered.active = testEl.$.child2a;
        setTimeout(function() {
          testEl.$.parentFiltered.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach resizables then notify parent', function(done) {
        registerResizeHandler(testEl.$.parentFiltered);
        registerResizeHandler(testEl.$.child2a, false);
        registerResizeHandler(testEl.$.child2b, false);
        registerResizeHandler(testEl.$.shadow2c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow2d.$.resizable);
        testEl.$.child2a.remove();
        testEl.$.shadow2c.remove();
        testEl.$.parentFiltered.active = testEl.$.shadow2d.$.resizable;
        setTimeout(function() {
          testEl.$.parentFiltered.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach parent then notify window', function(done) {
        registerResizeHandler(testEl.$.parentFiltered, false);
        registerResizeHandler(testEl.$.child2a, false);
        registerResizeHandler(testEl.$.child2b, false);
        registerResizeHandler(testEl.$.shadow2c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow2d.$.resizable, false);
        testEl.$.parentFiltered.remove();
        testEl.$.parentFiltered.active = testEl.$.shadow2d.$.resizable;
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

    });

    suite('core-resizer-peer', function() {

      test('notify resizables from window', function(done) {
        registerResizeHandler(testEl.$.peer);
        registerResizeHandler(testEl.$.child3a);
        registerResizeHandler(testEl.$.child3b);
        registerResizeHandler(testEl.$.shadow3c.$.resizable);
        registerResizeHandler(testEl.$.shadow3d.$.resizable);
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from peer', function(done) {
        registerResizeHandler(testEl.$.peer);
        registerResizeHandler(testEl.$.child3a);
        registerResizeHandler(testEl.$.child3b);
        registerResizeHandler(testEl.$.shadow3c.$.resizable);
        registerResizeHandler(testEl.$.shadow3d.$.resizable);
        setTimeout(function() {
          testEl.$.peer.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach resizables then notify', function(done) {
        registerResizeHandler(testEl.$.peer);
        registerResizeHandler(testEl.$.child3a, false);
        registerResizeHandler(testEl.$.child3b);
        registerResizeHandler(testEl.$.shadow3c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow3d.$.resizable);
        testEl.$.child3a.remove();
        testEl.$.shadow3c.remove();
        setTimeout(function() {
          testEl.$.peer.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach peer then notify', function(done) {
        registerResizeHandler(testEl.$.peer);
        registerResizeHandler(testEl.$.child3a, false);
        registerResizeHandler(testEl.$.child3b);
        registerResizeHandler(testEl.$.shadow3c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow3d.$.resizable);
        testEl.$.peer.remove();
        setTimeout(function() {
          testEl.$.peer.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

    });

    suite('core-resizer-peer-filtered', function(done) {

      test('notify resizables from window', function(done) {
        registerResizeHandler(testEl.$.peerFiltered);
        registerResizeHandler(testEl.$.child4a);
        registerResizeHandler(testEl.$.child4b, false);
        registerResizeHandler(testEl.$.shadow4c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow4d.$.resizable, false);
        testEl.$.peerFiltered.active = testEl.$.child4a;
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from peer', function(done) {
        registerResizeHandler(testEl.$.peerFiltered);
        registerResizeHandler(testEl.$.child4a);
        registerResizeHandler(testEl.$.child4b, false);
        registerResizeHandler(testEl.$.shadow4c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow4d.$.resizable, false);
        testEl.$.peerFiltered.active = testEl.$.child4a;
        setTimeout(function() {
          testEl.$.peerFiltered.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach resizables then notify parent', function(done) {
        registerResizeHandler(testEl.$.peerFiltered);
        registerResizeHandler(testEl.$.child4a, false);
        registerResizeHandler(testEl.$.child4b, false);
        registerResizeHandler(testEl.$.shadow4c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow4d.$.resizable);
        testEl.$.child4a.remove();
        testEl.$.shadow4c.remove();
        testEl.$.peerFiltered.active = testEl.$.shadow4d.$.resizable;
        setTimeout(function() {
          testEl.$.peerFiltered.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach peer then notify window', function(done) {
        registerResizeHandler(testEl.$.peerFiltered, false);
        registerResizeHandler(testEl.$.child4a, false);
        registerResizeHandler(testEl.$.child4b, false);
        registerResizeHandler(testEl.$.shadow4c.$.resizable, false);
        registerResizeHandler(testEl.$.shadow4d.$.resizable, false);
        testEl.$.peerFiltered.remove();
        testEl.$.peerFiltered.active = testEl.$.shadow4d.$.resizable;
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

    });

    suite('core-resizer-nested', function() {

      test('notify resizables from window', function(done) {
        registerResizeHandler(testEl.$.parentTop);
        registerResizeHandler(testEl.$.parentNested);
        registerResizeHandler(testEl.$.peerNested);
        registerResizeHandler(testEl.$.child5a);
        registerResizeHandler(testEl.$.shadow5b.$.resizable);
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from top parent', function(done) {
        registerResizeHandler(testEl.$.parentTop);
        registerResizeHandler(testEl.$.parentNested);
        registerResizeHandler(testEl.$.peerNested);
        registerResizeHandler(testEl.$.child5a);
        registerResizeHandler(testEl.$.shadow5b.$.resizable);
        setTimeout(function() {
          testEl.$.parentTop.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from nested parent', function(done) {
        registerResizeHandler(testEl.$.parentTop, false);
        registerResizeHandler(testEl.$.parentNested);
        registerResizeHandler(testEl.$.peerNested);
        registerResizeHandler(testEl.$.child5a);
        registerResizeHandler(testEl.$.shadow5b.$.resizable);
        setTimeout(function() {
          testEl.$.parentNested.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('notify resizables from nested peer', function(done) {
        registerResizeHandler(testEl.$.parentTop, false);
        registerResizeHandler(testEl.$.parentNested, false);
        registerResizeHandler(testEl.$.peerNested);
        registerResizeHandler(testEl.$.child5a);
        registerResizeHandler(testEl.$.shadow5b.$.resizable);
        setTimeout(function() {
          testEl.$.peerNested.notifyResize();
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      // Known limitation: peers of detached `resizerIsPeer` won't be notified
      // by parent resizers; ROI on that bookkeeping not considered high enough
      test('detach peer then notify', function(done) {
        registerResizeHandler(testEl.$.parentTop);
        registerResizeHandler(testEl.$.parentNested);
        registerResizeHandler(testEl.$.peerNested, false);
        registerResizeHandler(testEl.$.child5a, false);
        registerResizeHandler(testEl.$.shadow5b.$.resizable, false);
        testEl.$.peerNested.remove();
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach resizables then notify', function(done) {
        registerResizeHandler(testEl.$.parentTop);
        registerResizeHandler(testEl.$.parentNested);
        registerResizeHandler(testEl.$.peerNested, false); // removed in above test
        registerResizeHandler(testEl.$.child5a, false);
        registerResizeHandler(testEl.$.shadow5b.$.resizable, false);
        testEl.$.child5a.remove();
        testEl.$.shadow5b.remove();
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

      test('detach top parent then notify', function(done) {
        registerResizeHandler(testEl.$.parentTop, false);
        registerResizeHandler(testEl.$.parentNested, false);
        registerResizeHandler(testEl.$.peerNested, false);
        registerResizeHandler(testEl.$.child5a, false);
        registerResizeHandler(testEl.$.shadow5b.$.resizable, false);
        testEl.$.parentTop.remove();
        setTimeout(function() {
          window.dispatchEvent(new CustomEvent('resize', { bubbles: false }));
          assert(notifyPending.length === 0, 'all resizables were not notified');
          unregisterResizeHandlers();
          done();
        });
      });

    });

  });

</script>

</body>
</html>
